package cn.iocoder.yudao.module.dify.service;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.dify.api.vo.req.DifyRequestBody;
import cn.iocoder.yudao.module.dify.api.vo.resp.BlockResponse;
import cn.iocoder.yudao.module.dify.api.vo.resp.DifyChatFlowUploadResponse;
import cn.iocoder.yudao.module.dify.api.vo.resp.ResponseData;
import cn.iocoder.yudao.module.dify.api.vo.resp.StreamResponse;
import cn.iocoder.yudao.module.dify.dal.dataobject.fileprocessing.FileProcessingDO;
import cn.iocoder.yudao.module.dify.util.DifyFileUploadUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vladsch.flexmark.ext.footnotes.FootnoteExtension;
import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.util.ast.Document;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.html.HtmlWriter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;

@Service
@RequiredArgsConstructor
@Slf4j
public class DifyService {

    @Value("${spring.dify.url}")
    private String difyUrl;
    @Value("${spring.dify.uploadUrl}")
    private String difyUploadUrl;
    @Value("${spring.dify.key.test}")
    private String difyKey;


    private final RestTemplate restTemplate;

    private final WebClient webClient;

    /**
     * 流式调用dify.
     *
     * @param query  查询文本
     * @param userId 用户id
     * @param apiKey apiKey 通过 apiKey 获取权限并区分不同的 dify 应用
     * @return Flux 响应流
     */
    public Flux<StreamResponse> streamingMessage(String query, Long userId, String apiKey) {
        //1.设置请求体
        DifyRequestBody body = new DifyRequestBody();
        body.setInputs(new HashMap<>());
        body.setQuery(query);
        body.setResponseMode("streaming");
        body.setConversationId("");
        body.setUser(userId.toString());
        //2.使用webclient发送post请求
        return webClient.post()
                .uri(difyUrl)
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.setBearerAuth(apiKey);
                })
                .bodyValue(JSON.toJSONString(body))
                .retrieve()
                .bodyToFlux(StreamResponse.class);
    }


    /**
     * 阻塞式调用dify.
     *
     * @param query  查询文本
     * @param userId 用户id
     * @param apiKey apiKey 通过 apiKey 获取权限并区分不同的 dify 应用
     * @return BlockResponse
     */
    public BlockResponse blockingMessage(String query, Long userId, String apiKey) {
        //1.设置请求体
        DifyRequestBody body = new DifyRequestBody();
        body.setInputs(new HashMap<>());
        body.setQuery(query);
        body.setResponseMode("blocking");
        body.setConversationId("");
        body.setUser(userId.toString());
        //2.设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList((MediaType.APPLICATION_JSON)));
        headers.setBearerAuth(apiKey);
        //3.封装请求体和请求头
        String jsonString = JSON.toJSONString(body);
        HttpEntity<String> entity = new HttpEntity<>(jsonString, headers);
        //4.发送post请求，阻塞式
        ResponseEntity<BlockResponse> stringResponseEntity =
                restTemplate.postForEntity(difyUrl, entity, BlockResponse.class);
        //5.返回响应体
        return stringResponseEntity.getBody();
    }


    /**
     * 通过dify接口上传用户文件信息
     */
    public String uploadFileByDify(FileProcessingDO fileProcessingDO) throws IOException {
        Assert.notNull(fileProcessingDO, "信息为空");
        String originalFilepath = fileProcessingDO.getOriginalFilepath();
        //获取返回的内容
        String s = DifyFileUploadUtil.uploadViaMultipart(difyUploadUrl, difyKey, originalFilepath, getLoginUserId());

        return s;

    }

    public DifyChatFlowUploadResponse chatFlowUpload(String difyKey, MultipartFile file, Long userId) throws IOException {
        String apiUrl = "http://47.115.137.160/v1/files/upload";
        String apiKey = difyKey; // 替换为实际的 API Key
//        String filePath = "C:\\Users\\xiezheng\\Desktop\\2022工\\puyuan-test\\39.耳腔式医用红外体温计注册审查指导原则（2024年修订版）（征求意见稿）.docx"; // 替换为本地文件路径
        String user = userId.toString();
        RestTemplate restTemplate = new RestTemplate();
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.setBearerAuth(apiKey);
        // 构建表单数据
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        // ✅ 使用 MultipartFile 构建 ByteArrayResource 避免临时文件
        ByteArrayResource resource = new ByteArrayResource(file.getBytes()) {
            @Override
            public String getFilename() {
                return file.getOriginalFilename(); // 保留原始文件名
            }
        };
//        FileSystemResource fileResource = new FileSystemResource(new File(filePath));
        body.add("file", resource);
        body.add("user", user);
        // 封装请求
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        // 发送 POST 请求
        ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, requestEntity, String.class);

        // 输出响应结果
        System.out.println("Response Body: " + response.getBody());
        return JSON.parseObject(response.getBody(), DifyChatFlowUploadResponse.class);

    }

    @TenantIgnore
    public Flux<ResponseData> riskManagementReportTest(DifyChatFlowUploadResponse difyChatFlowUploadResponse, String query, Long userId, String apiKey) {
        String apiUrl = "http://47.115.137.160/v1/chat-messages";
        StringBuffer stringBuffer = new StringBuffer("");
        RestTemplate restTemplate = new RestTemplate();
        //hutianhao.123
        // 构建请求头
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
//        headers.setBearerAuth(apiKey);

        // 构建请求体
        Map<String, Object> requestBody = new HashMap<>();
        Map<String, Object> inputsMap = new HashMap<>();

        requestBody.put("query", query);
        requestBody.put("response_mode", "streaming");
        requestBody.put("conversation_id", "");

        // 设置 user 字段
        requestBody.put("user", userId);

        // 构建 files 数组
        List<Map<String, Object>> files = new ArrayList<>();

        Map<String, Object> file = new HashMap<>();
        file.put("type", "document");
        file.put("transfer_method", "local_file");
        file.put("upload_file_id", difyChatFlowUploadResponse.getId());

        files.add(file);
        requestBody.put("files", files);
        inputsMap.put("fileList", files);
        inputsMap.put("query", query);
        requestBody.put("inputs", inputsMap);
        String jsonString = JSONObject.toJSONString(requestBody);
        log.info("requestBody=============>" + jsonString);

        // 封装 HttpEntity
//        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        // 发送 POST 请求
//        ResponseEntity<String> responseEntity = restTemplate.postForEntity(apiUrl, requestEntity, String.class);

        // 输出响应结果
//        System.out.println("Status Code: " + responseEntity.getStatusCode());
//        System.out.println("Response Body: " + responseEntity.getBody());
        Flux<ResponseData> responseDataFlux = webClient.post()
                .uri(apiUrl)
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.setBearerAuth(apiKey);
                })
                .bodyValue(requestBody)
                .retrieve()
                .bodyToFlux(ResponseData.class)
                .doOnNext(responseData -> {
                        stringBuffer.append(responseData.getAnswer());
                        log.info("Received data: {}", responseData);
                });
        responseDataFlux.subscribe(responseData -> stringBuffer.append(responseData.getAnswer()));
        try (FileWriter writer = new FileWriter("Answers.md")) {
            writer.write(stringBuffer.toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
//        Disposable subscribe = responseDataFlux.subscribe(s -> stringBuffer.append(s.getAnswer()));
        return
                responseDataFlux;
//                webClient.post()
//                        .uri(apiUrl)
//                        .headers(httpHeaders -> {
//                            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
//                            httpHeaders.setBearerAuth(apiKey);
//                        })
//                        .bodyValue(requestBody)
//                        .retrieve()
//                        .bodyToFlux(ResponseData.class)
//                        .doOnNext(data -> log.info("Received data: {}", data))
//                        .doOnNext(responseData -> stringBuffer.append(responseData.getAnswer()))
//                        .doOnError(ex -> log.error("==========流式调用失败=======", ex));

    }

}